/*
 *  Copyright (C) void Team 2010 Pedro Batista
 * 
 *  http://code.google.com/p/capacitec
 * 
 *  This file is part of capacitec.
 * 
 *  capacitec is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  capacitec is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with capacitec.  If not, see <http://www.gnu.org/licenses/>.
 */
package dao;

import br.com.caelum.vraptor.ioc.Component;
import entidades.AlunoSubPrograma;
import entidades.AlunoSubProgramaTurma;
import entidades.Curso;
import entidades.SubPrograma;
import entidades.Turma;
import java.util.List;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 * Responsável por fazer operações no banco de dados envolvendo a classe
 * SubPrograma.
 * @author Pedro Batista
 */
@Component
public class SubProgramaDao {

	private final Session session;
	private final TurmaDao turmaDao;
	private final AlunoSubProgramaTurmaDao alunoSubProgramaTurmaDao;

	/**
	 * @param session Sessão do hibernate para acessar o banco de dados.
	 * @param turmaDao
	 * @param alunoSubProgramaTurmaDao
	 */
	public SubProgramaDao(Session session, TurmaDao turmaDao, AlunoSubProgramaTurmaDao alunoSubProgramaTurmaDao) {
		this.session = session;
		this.turmaDao = turmaDao;
		this.alunoSubProgramaTurmaDao = alunoSubProgramaTurmaDao;
	}

	/**
	 * Adiciona um novo sub programa ao banco de dados.
	 * @param subPrograma Novo sub programa a ser adicionado.
	 */
	public void salva(SubPrograma subPrograma) {
		Transaction tx = session.beginTransaction();
		session.save(subPrograma);
		tx.commit();
	}

	/**
	 * Busca no banco de dados o sub programa com o id.
	 * @param id Id do sub programa a ser buscado.
	 * @return
	 */
	public SubPrograma carrega(Integer id) {
		SubPrograma subPrograma;
		subPrograma = (SubPrograma) session.load(SubPrograma.class, id);
		return subPrograma;
	}

	/**
	 * Busca todos os sub programas presentes no banco.
	 * @return Lista com os sub programas encontrados.
	 */
	public List<SubPrograma> carrega() {
		return session.createCriteria(SubPrograma.class).list();
	}

	/**
	 * Recarrega o sub programa subPrograma se nesse existir o seu id.
	 * @param subPrograma Sub programa contendo o id a ser recarregado.
	 */
	public void recarrega(SubPrograma subPrograma) {
		session.refresh(subPrograma);
	}

	/**
	 * Vincula o aluno ao subprograma em alunoSubPrograma a todos os cursos
	 * do subprograma, para isso devem haver turmas para todos os cursos.
	 * @param alunoSubPrograma aluno e subprograma serem vinculados
	 * @throws Exception caso não se consigo adicionar o aluno em alguma turma.
	 */
	public void matricula(AlunoSubPrograma alunoSubPrograma) throws Exception {
		//TODO: fazer com que só se possa matricular quando todos os cursos daquele
		//subprograma ja estiverem cadastrados.
		SubPrograma subPrograma = alunoSubPrograma.getSubPrograma();
		boolean matriculado;
		AlunoSubProgramaTurma novoASPT;

		for (Curso curso : subPrograma.getCursoList()) {
			matriculado = false;

			for (Turma turma : curso.getTurmaList()) {
				if (turma.getNumeroDeVagas() <= turmaDao.vagasPreenchidas(turma)) {
					continue;
				} else {
					novoASPT =
						new AlunoSubProgramaTurma(
						alunoSubPrograma.getAluno().getPessoaId(),
						subPrograma.getId(),
						curso.getId());
					novoASPT.setTurma(turma);
					alunoSubProgramaTurmaDao.salva(novoASPT);
					matriculado = true;
					break;
				}
			}

			if (!matriculado) {
				//TODO: Informar a causa do erro.
				throw new Exception("Não conseuiu matricular o aluno");
			}
		}
	}

	public void desvincula(AlunoSubPrograma alunoSubPrograma) {
		alunoSubProgramaTurmaDao.apaga(alunoSubPrograma.getAluno().getPessoaId());
	}

	public List<SubPrograma> carregaAbertos() {
		SQLQuery query = session.createSQLQuery("SELECT * FROM subPrograma WHERE situacao = 'aberto'");
		query.addEntity(SubPrograma.class);
		return query.list();
	}

	/**
	 *
	 * @param subPrograma subprograma com id setado a ser atualizado.
	 */
	public void atualiza(SubPrograma subPrograma){
		Transaction tx = session.beginTransaction();
		session.update(subPrograma);
		tx.commit();
	}
}
